package com.njym.payment.wxpay.service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.result.WxPayBillInfo;
import com.github.binarywang.wxpay.bean.result.WxPayBillResult;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.njym.entity.PlatformBusinessRec;
import com.njym.payment.wxpay.GetWxPayClient;
import com.njym.payment.wxpay.WxPayController;
import com.njym.service.PlatformBusinessRecService;
import com.njym.tradeStatusConfig.WxTradeStatus;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;

/**
 * @program: WxService
 * @description:
 * @author: yh
 * @create: 2018-09-11 17:47
 **/
@Service
public class WxService {
    private static final org.slf4j.Logger log = LoggerFactory.getLogger(WxService.class);

    @Autowired
    private WxPayController wxPayController;

    @Resource
    private GetWxPayClient wxPayClient;

    @Autowired
    private PlatformBusinessRecService platformBusinessRecService;

    private SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    private final static RejectedExecutionHandler HANDLER = new ThreadPoolExecutor.CallerRunsPolicy();

    private final static ThreadFactory THREAD_FACTORY = new ThreadFactoryBuilder().setNameFormat("queryRefund-pool-%d").build();

    private  ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(2, THREAD_FACTORY, HANDLER);

    /**
     * method: downloadWxPayBill
     *
     * @Description:
     * @param: [orgId, billDate 格式如：20180609]
     * @return: com.alibaba.fastjson.JSONObject
     * @author: yh
     * @date: 2018/9/14 0:36
     */
    public JSONObject downloadWxPayBill(String orgId, String modeId, String billDate) {
        String wxBillDate = billDate.replace("-", "");
        JSONObject json = new JSONObject();
        WxPayService wxPayService = wxPayClient.getWxService(orgId);
        try {
            WxPayBillResult wxPayBillResult = wxPayService.downloadBill(wxBillDate, "ALL", "GZIP", "");
            List<WxPayBillInfo> wxPayBillBaseResultList = wxPayBillResult.getBillInfoList();

            Wrapper<PlatformBusinessRec> queryParams = new EntityWrapper<>();
            queryParams.isNotNull("trade_no");
            queryParams.eq("org_id", orgId);
            queryParams.eq("mode_id", modeId);
            queryParams.between("trade_date", billDate + " 00:00:00", billDate + " 23:59:59");

            List<PlatformBusinessRec> platformBusinessRecList = platformBusinessRecService.selectList(queryParams);
            if (wxPayBillBaseResultList.size() > 0) {
                //将微信对账单和平台交易记录对比
                try {
                     for (WxPayBillInfo wxPayBillBaseResult : wxPayBillBaseResultList) {
	                     String thirdOutTradeNo="" ;
	                     String thirdRefundNo="";
	                     Byte recType;
	                     String tradeState = wxPayBillBaseResult.getTradeState();
	                     if (WxTradeStatus.SUCCESS.equals(tradeState)) {
		                     thirdOutTradeNo = wxPayBillBaseResult.getOutTradeNo();
                             recType=Byte.valueOf("1");
	                     } else if (WxTradeStatus.REFUND.equals(tradeState)) {
                             thirdRefundNo = wxPayBillBaseResult.getOutRefundNo();
                             recType=Byte.valueOf("2");
	                     } else {
		                     break;
	                     }
                          boolean existFlag = false;
                               for (PlatformBusinessRec businessRec : platformBusinessRecList) {
                                   // 正常交易的，outTradeNo对比
                                   if(businessRec.getRecType().equals(Byte.valueOf("1"))){
                                       if(businessRec.getOutTradeNo().equals(thirdOutTradeNo)){
                                           existFlag = true;
                                           break;
                                       }
                                       // 退款的比较退款单号
                                   }else if(businessRec.getRecType().equals(Byte.valueOf("2"))){
                                       if(businessRec.getOutRequestNo().equals(thirdRefundNo)){
                                           existFlag = true;
                                           break;
                                       }
                                   }
                               }
                               if (!existFlag&&platformBusinessRecList.size()>0) {
                                    //平台不存在记录微信存在，存到数据库
	                               PlatformBusinessRec platformBusinessRec = new PlatformBusinessRec();
                                   platformBusinessRec.setOrgId(platformBusinessRecList.get(0).getOrgId());
                                   platformBusinessRec.setChannelId(platformBusinessRecList.get(0).getChannelId());
                                   platformBusinessRec.setModeId(platformBusinessRecList.get(0).getModeId());
                                   platformBusinessRec.setTradeNo(wxPayBillBaseResult.getTransactionId());
                                   platformBusinessRec.setOutTradeNo(thirdOutTradeNo);
                                   platformBusinessRec.setOutRequestNo(thirdRefundNo);
                                   platformBusinessRec.setRecType(recType);
                                   platformBusinessRec.setTotalFee(new BigDecimal(wxPayBillBaseResult.getTotalFee()).setScale(2, BigDecimal.ROUND_HALF_UP));
                                   Date date = null;
                                   try {
                                       date = fmt.parse(wxPayBillBaseResult.getTradeTime());
                                   }catch (ParseException e){
                                       log.info("时间转化异常:"+wxPayBillBaseResult.getTradeTime(), e);
                                       e.printStackTrace();
                                   }
                                   platformBusinessRec.setTradeDate(date);
                                   platformBusinessRec.setAccountFlag(Byte.valueOf("0"));
                                   platformBusinessRec.setAbnormalFlag(Byte.valueOf("0"));
                                   platformBusinessRec.setDeleted(Byte.valueOf("0"));
                                   platformBusinessRec.setCreateDate(date);
                                   platformBusinessRecService.insert(platformBusinessRec);
                               }
                          }
                    for (PlatformBusinessRec businessRec : platformBusinessRecList) {
                        boolean existFlag = false;
                        String outTradeNo = businessRec.getOutTradeNo();
                        String thirdOutTradeNo;
                        for (WxPayBillInfo wxPayBillBaseResult : wxPayBillBaseResultList) {
                            String tradeState = wxPayBillBaseResult.getTradeState();
                            if (WxTradeStatus.SUCCESS.equals(tradeState)) {
                                thirdOutTradeNo = wxPayBillBaseResult.getOutTradeNo();
                            } else if (WxTradeStatus.REFUND.equals(tradeState)) {
                                thirdOutTradeNo = wxPayBillBaseResult.getOutRefundNo();
                            } else {
                                break;
                            }
                            if (outTradeNo.equals(thirdOutTradeNo)) {
                                existFlag = true;
                            }
                        }
                        if (!existFlag) {
                            //支付宝不存在平台记录存在
                            //1号交易10元  2号退款5元。3号对2号账时退款不在2号，在1号里
//                            businessRec.deleteById();
                        }
                    }
                }
                catch (Exception e) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                }
            }
        }
        catch (WxPayException e) {
            System.err.print(e.getReturnMsg());
        }
        return json;
    }

    public String refund(String orgId, String outTradeNo, String outRefundNo, String totalFee, String refundFee, String refundReason,String operatorId,String operatorName,String channelId) {

        WxPayRefundRequest wxPayRefundRequest = new WxPayRefundRequest();
        wxPayRefundRequest.setOutTradeNo(outTradeNo);
        wxPayRefundRequest.setOutRefundNo(outRefundNo);
        BigDecimal totalFeeBd = null;
        int totalFeeInt = 0;
        int refundFeeInt = 0;
        try {
            totalFeeBd = new BigDecimal(totalFee).setScale(2, BigDecimal.ROUND_HALF_UP);
            totalFeeInt = totalFeeBd.multiply(new BigDecimal(100)).intValue();
        }
        catch (Exception e) {
        }
        try {
            refundFeeInt = totalFeeBd.multiply(new BigDecimal(100)).intValue();
        }
        catch (Exception e) {
        }
        wxPayRefundRequest.setTotalFee(totalFeeInt);
        wxPayRefundRequest.setRefundFee(refundFeeInt);
        wxPayRefundRequest.setRefundDesc(refundReason);
        String result;
        try {
            WxPayService wxPayService = wxPayClient.getWxService(orgId);
            wxPayRefundRequest.setNotifyUrl(wxPayClient.getWxPayProperties(orgId).getRefundNotifyUrl());
            WxPayRefundResult refundResult = wxPayService.refund(wxPayRefundRequest);
            String returnCode = refundResult.getReturnCode();
            String resultCode = refundResult.getResultCode();
            // 处理微信返回结果
            if (WxTradeStatus.SUCCESS.equals(returnCode)) {
                if (WxTradeStatus.SUCCESS.equals(resultCode)) {
                    scheduledThreadPoolExecutor.schedule(() -> {
                        wxPayController.queryMyRefundStatus(orgId, outTradeNo);
                    }, 20, TimeUnit.SECONDS);
                    // 将退款记录保存到数据库
                    PlatformBusinessRec businessRec = new PlatformBusinessRec();
                    businessRec.setOrgId(orgId);
                    businessRec.setChannelId(channelId);
                    businessRec.setModeId(wxPayClient.getModeById(orgId).getId());
                    businessRec.setRecType(Byte.valueOf("2"));
                    //微信退款单号只在退款成功时记录
                    businessRec.setOutTradeNo(outTradeNo);
                    businessRec.setOutRequestNo(outRefundNo);
                    businessRec.setTotalFee(totalFeeBd);
                    businessRec.setTradeDate(new Date());
                    businessRec.setAccountFlag(Byte.valueOf("0"));
                    businessRec.setAbnormalFlag(Byte.valueOf("0"));
                    businessRec.setCreateDate(new Date());
                    businessRec.setOperatorId(operatorId);
                    businessRec.setOperatorName(operatorName);
                    platformBusinessRecService.insert(businessRec);
                    result = "SUCCESS";
                } else {
                    result = "FAIL";
                }
            } else {
                result = "FAIL";
            }
        }
        catch (WxPayException e) {
            result = "FAIL";
        }
        catch (Exception e) {
            result = "FAIL";
        }
        return result;
    }

}
